package com.ruoyi.integration.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.exception.integrationEnum.MapRenderException;
import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.integration.config.MapRenderServiceProperties;
import com.ruoyi.integration.dto.*;
import com.ruoyi.integration.service.MapRenderService;
import io.swagger.util.Json;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.client.WebClient;

import java.util.List;
import java.util.Objects;

import static com.ruoyi.integration.constants.MapRenderActionConstants.*;
import static com.ruoyi.integration.constants.MapRenderRequestParamConstants.*;

@Service
@Slf4j
@RequiredArgsConstructor
public class MapRenderServiceImpl implements MapRenderService {

    private final MapRenderServiceProperties mapRenderServiceProperties;

    private final WebClient webClient;

    private final static Logger logger = LoggerFactory.getLogger(MapRenderServiceImpl.class);

    @Value("${minio-bucket.slices}")
    private String SLICES_BUCKET;

    @Value("${storage-location.windows}")
    private String WINDOWS_PATH_PREFIX;

    private String postForm(MultiValueMap<String, String> params) {

        String url = mapRenderServiceProperties.getEndpoint().getBaseUrl();
        String apiRouter = mapRenderServiceProperties.getApiRouter().getRender();

        // 日志记录请求体
        logger.info("Request Body: {}", params);

        /*
         * BodyInserters.fromFormData(params) 是 Spring WebFlux 框架中的一个工具方法:
         * 用于创建一个 BodyInserter 实例，它能够将表单数据作为 HTTP 请求体插入到请求中。
         */

        return webClient.post()
                .uri(url + apiRouter)
                .contentType(MediaType.MULTIPART_FORM_DATA)
                .body(BodyInserters.fromFormData(params))
                .retrieve()
                .bodyToMono(String.class)
                .block();
    }


    /**
     * 获取生态图Z值取值范围及分类数据
     *
     * @param minioBucket
     * @param minioObject
     * @param jenksCount
     * @return JSONObject
     */
    @Override
    public JSONObject getRifZRange(String minioBucket, String minioObject, Integer jenksCount) {

        // 构建fileUrl: 在windows中. 使用静态前缀 + minionbucket + minioObject 拼接而成
        String fileUrl = WINDOWS_PATH_PREFIX + minioBucket + "\\" + minioObject;

        // 构建参数
        MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
        params.add(ACTION.getValue(), GET_TIF_Z_RANGE.getValue());
        params.add(FILE_URL.getValue(), fileUrl);
        params.add(JENKS_COUNT.getValue(), String.valueOf(jenksCount));

        String response = postForm(params);
        log.info("Response Body: {}", response);

        // 返回响应结果
        if (response != null && !response.isEmpty()) {
            // 判断响应状态码
            if (response.contains("\"success\":\"false\"")) {
                logger.error("getRifZRange fail messages: {}", Objects.requireNonNull(JSONObject.parseObject(response)).get("message"));
                throw new ServiceException(MapRenderException.WINDOWS_SERVICES_ERROR);
            }
            return JSONObject.parseObject(response);
        }
        throw new ServiceException(MapRenderException.UNKNOWN_ERROR);
    }


    /**
     * 获取生态图Z值取值范围及分类数据
     *
     * @param minioBucket
     * @param minioObject
     * @return JSONObject
     */
    @Override
    public JSONObject getTifClassfi(String minioBucket, String minioObject) {

        //构建fileUrl
        String fileUrl = WINDOWS_PATH_PREFIX + minioBucket + "\\" + minioObject;


        //构建参数
        MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
        params.add(ACTION.getValue(), GET_TIF_CLASSFI.getValue());
        params.add(FILE_URL.getValue(), fileUrl);

        //发送请求
        String response = postForm(params);

        // 返回响应结果
        if (response != null && !response.isEmpty()) {
            // 判断响应状态码
            if (response.contains("\"success\":\"false\"")) {
                logger.error("getTiffClassfi fail messages: {}", Objects.requireNonNull(JSONObject.parseObject(response)).get("message"));
                throw new ServiceException(MapRenderException.WINDOWS_SERVICES_ERROR);
            }
            return JSONObject.parseObject(response);
        }
        throw new ServiceException(MapRenderException.UNKNOWN_ERROR);


    }


    /**
     * 获取全局生态图Z值范围及分自然分级法断点数据
     *
     * @param globalZRangeRequestDTO
     * @return JSONObject
     */
    @Override
    public JSONObject getTifGlobalZRange(GlobalZRangeRequestDTO globalZRangeRequestDTO) {

        //获取jentksCount
        String jentksCount = String.valueOf(globalZRangeRequestDTO.getJenksCount());

        //获取tiffSet
        List<GlobalZRangeRequestDTO.TiffSet> tiffSetList = globalZRangeRequestDTO.getTiffSet();

        //构建参数
        MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
        StringBuilder fileUrls = new StringBuilder();
        for (GlobalZRangeRequestDTO.TiffSet tiffSet : tiffSetList) {
            String minioBucket = tiffSet.getMinioBucket();
            String minioObject = tiffSet.getMinioObject();
            String fileUrl = WINDOWS_PATH_PREFIX + minioBucket + "\\" + minioObject;
            fileUrls.append(fileUrl).append(",");
        }
        params.add(ACTION.getValue(), GET_TIF_GLOBAL_Z_RANGE.getValue());
        params.add(FILE_URLS.getValue(), fileUrls.toString());
        params.add(JENKS_COUNT.getValue(), jentksCount);

        //发送请求
        String response = postForm(params);

        // 返回响应结果
        if (response != null && !response.isEmpty()) {
            // 判断响应状态码
            if (response.contains("\"success\":\"false\"")) {
                logger.error("getTifGlobalZRange fail messages: {}", Objects.requireNonNull(JSONObject.parseObject(response)).get("message"));
                throw new ServiceException(MapRenderException.WINDOWS_SERVICES_ERROR);
            }
            return JSONObject.parseObject(response);
        }
        throw new ServiceException(MapRenderException.UNKNOWN_ERROR);

    }

    @Override
    public JSONObject tif2HeatMap(HeatMapRequestDTO heatMapRequestDTO){

        try {
            //构建fileUrl
            String minioBucket = heatMapRequestDTO.getMinioBucket();
            String minioObject = heatMapRequestDTO.getMinioObject();
            String fileUrl = WINDOWS_PATH_PREFIX + minioBucket + "\\" + minioObject;

            //构建参数
            MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
            params.add(ACTION.getValue(), TIF_2_HEAT_MAP.getValue());
            params.add(FILE_URL.getValue(), fileUrl);
            params.add(COLOR_TABLE.getValue(), Json.mapper().writeValueAsString(heatMapRequestDTO.getColorTable()));

            //发送请求
            String response = postForm(params);
            logger.info("Response Body: {}", response);

            // 返回响应结果
            if (response != null && !response.isEmpty()) {
                // 判断响应状态码
                if (response.contains("\"success\":\"false\"")) {
                    logger.error("getTif2HeatMap fail messages: {}", Objects.requireNonNull(JSONObject.parseObject(response)).get("message"));
                    throw new ServiceException(MapRenderException.WINDOWS_SERVICES_ERROR);
                }
                return JSONObject.parseObject(response);
            }
        } catch (Exception e) {
            logger.error("getTif2HeatMap fail messages: {}", e.getMessage());
            throw new ServiceException(MapRenderException.UNKNOWN_ERROR);
        }
        logger.error("调用未返回任何数据");
        throw new ServiceException(MapRenderException.UNKNOWN_ERROR);
    }


    /**
     * 根据指定经纬度获取生态图Z值
     *
     * @param zFromLonLatRequestDTO
     * @return
     */
    @Override
    public JSONObject getTifZData(ZFromLonLatRequestDTO zFromLonLatRequestDTO) {

        //构建fileUrl
        String minioBucket = zFromLonLatRequestDTO.getMinioBucket();
        String minioObject = zFromLonLatRequestDTO.getMinioObject();
        String fileUrl = WINDOWS_PATH_PREFIX + minioBucket + "\\" + minioObject;

        //构建参数
        MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
        params.add(ACTION.getValue(), GET_TIF_Z_DATA.getValue());
        params.add(FILE_URL.getValue(), fileUrl);
        params.add(LNG.getValue(), zFromLonLatRequestDTO.getLng());
        params.add(LAT.getValue(), zFromLonLatRequestDTO.getLat());

        //发送请求
        String response = postForm(params);

        // 返回响应结果
        if (response != null && !response.isEmpty()) {
            // 判断响应状态码
            if (response.contains("\"success\":\"false\"")) {
                logger.error("getTifZData fail messages: {}", Objects.requireNonNull(JSONObject.parseObject(response)).get("message"));
                throw new ServiceException(MapRenderException.WINDOWS_SERVICES_ERROR);
            }
            return JSONObject.parseObject(response);
        }
        throw new ServiceException(MapRenderException.UNKNOWN_ERROR);


    }


    /**
     * 多光谱RGB融合切片
     * @param rgbFusionSlicing
     * @return
     */
    @Override
    public JSONObject multisBandsTif2png(RGBFusionSlicing rgbFusionSlicing) {

        //构建fileUrl
        String minioBucket = rgbFusionSlicing.getMinioBucket();
        String minioObject = rgbFusionSlicing.getMinioObject();
        String fileUrl = WINDOWS_PATH_PREFIX + minioBucket + "\\" + minioObject;
        String bands = rgbFusionSlicing.getBands();

        //构建参数
        MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
        params.add(ACTION.getValue(), MUILTS_BANDS_STIF_2_PNG.getValue());
        params.add(FILE_URL.getValue(), fileUrl);
        params.add(BANDS.getValue(), bands);
        params.add(DST_FILE_PATH.getValue(), WINDOWS_PATH_PREFIX + SLICES_BUCKET + "\\" + FileUtils.getNameNotSuffix(minioObject));

        //发送请求
        String response = postForm(params);

        // 返回响应结果
        if (response != null && !response.isEmpty()) {
            // 判断响应状态码
            if (response.contains("\"success\":\"false\"")) {
                logger.error("multisBandsTif2png fail messages: {}", Objects.requireNonNull(JSONObject.parseObject(response)).get("message"));
                throw new ServiceException(MapRenderException.WINDOWS_SERVICES_ERROR);
            }
            return JSONObject.parseObject(response);
        }
        throw new ServiceException(MapRenderException.UNKNOWN_ERROR);

    }
}
